﻿Type.registerNamespace("RFBR.KnowledgeBase.Hierarchy");
RFBR.KnowledgeBase.Hierarchy = function (settings) {
    if (!settings) {
        settings = {};
    }
    if (!this._events) {
        this._events = [];
    }
    this._events = this._events.concat(["SelectionChanged", "NodeEdited"]);
    this._Width = 300;
    this._Height = 0;
    this._Nodes = null;
    this._Parent = null;
    settings.Inited = { func: this._init, context: this };
    this._DomNode = null;
    this._RootNode = null;
    RFBR.KnowledgeBase.Hierarchy.initializeBase(this, arguments);
};

var hierarchyProto = RFBR.KnowledgeBase.Hierarchy.prototype;

hierarchyProto._init = function () {
    this._render();
};

hierarchyProto._render = function () {
    this._DomNode = this._createBlock("div", "FancyTree");
    this._DomNode.id = "tree";
    $(this._createBlock("ul")).appendTo(this._DomNode);
    if (this._Parent) {
        $(this._DomNode).appendTo(this._Parent);
    }
    var self = this;
    var isMac = /Mac/.test(navigator.platform);
    $(this._DomNode).fancytree({
        extensions: ["dnd"],
        dnd: {
            preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
            preventRecursiveMoves: true, // Prevent dropping nodes on own descendants
            autoExpandMS: 400,
            onDragStart: function (node) {
                /** This function MUST be defined to enable dragging for the tree.
                 *  Return false to cancel dragging of node.
                 */
                return true;
            },
            onDragEnter: function (node, sourceNode) {
                /** sourceNode may be null for non-fancytree droppables.
                 *  Return false to disallow dropping on node. In this case
                 *  onDragOver and onDragLeave are not called.
                 *  Return 'over', 'before, or 'after' to force a hitMode.
                 *  Return ['before', 'after'] to restrict available hitModes.
                 *  Any other return value will calc the hitMode from the cursor position.
                 */
                // Prevent dropping a parent below another parent (only sort
                // nodes under the same parent)
                /*           if(node.parent !== sourceNode.parent){
                            return false;
                          }
                          // Don't allow dropping *over* a node (would create a child)
                          return ["before", "after"];
                */
                return true;
            },
            onDrop: function (node, sourceNode, hitMode, ui, draggable) {
                /** This function MUST be defined to enable dropping of items on
                 *  the tree.
                 */
                sourceNode.moveTo(node, hitMode);
            }
        },
        click: function(e, data) {
            if( e.shiftKey ){
                self._editNode(data.node);
                return false;
            }
        },
        dblclick: function(e, data) {
            self._editNode(data.node);
            return false;
        },
        keydown: function(e, data) {
            switch( e.which ) {
                case 113: // [F2]
                    self._editNode(data.node);
                    return false;
                case 13: // [enter]
                    if( isMac ){
                        self._editNode(data.node);
                        return false;
                    }
            }
        },
        //activate: function (e, data) {
        //    self._ActiveNode = data.node;
        //},
        focus: function (e, data) {
            self.SelectionChanged.fire(self, { node: data.node });
        },
        lazyread: function (e, data) {
            var fakeJsonResult = [
				{ title: 'Lazy node 1', lazy: true },
				{ title: 'Simple node 2', select: true }
            ];
            //              alert ("Let's pretend we're using this AJAX response to load the branch:\n " + jsonResult);
            function fakeAjaxResponse() {
                return function () {
                    node.addChild(fakeJsonResult);
                    // Remove the 'loading...' status:
                    node.setLazyNodeStatus(DTNodeStatus_Ok);
                };
            }
            window.setTimeout(fakeAjaxResponse(), 1500);
        }
    });
    this._RootNode = $(this._DomNode).fancytree("getRootNode");
    this.loadNodes();
};

hierarchyProto.setSize = function (width, height) {
    this._Width = width;
    this._Height = height;
    if (this._DomNode) {
        $(this._DomNode).width(width);
        $(this._DomNode).height(height)
    }
};

hierarchyProto.setHeight = function (height) {
    this._Height = height;
    $(this._DomNode).height(height);
};

hierarchyProto.getDomNode = function () {
    return this._DomNode;
};

hierarchyProto.loadNodes = function (nodes) {
    if (!nodes) nodes = this._Nodes;
    if (!nodes) return;
    this._loadChilds({ Childs: nodes, _DomNode: this._RootNode });
};

hierarchyProto._loadChilds = function (parent) {
    for (var i = 0; i < parent.Childs.length; i++) {
        var node = parent.Childs[i];
        //создание ноды
        node._DomNode = this.createNode(node, parent._DomNode);
        if (node.Childs && node.Childs.length > 0) {
            this._loadChilds(node);
        }
    }
};

hierarchyProto.createNode = function (node, parent) {
    if (!node) return;
    if (!parent) parent = this.getActiveNode() || this._RootNode.getFirstChild();
    parent.setExpanded(true);
    parent.expanded = true;
    return parent.addChildren({
        data: { Id: node.Id },
        title: node.Name,
        tooltip: node.Name
    });
};

hierarchyProto.getActiveNode = function () {
    return $(this._DomNode).fancytree("getActiveNode");
};

hierarchyProto.getSelectedNode = function () {
    var activeNode = $(this._DomNode).fancytree("getActiveNode");
    if (activeNode.isSelected()) return activeNode;
};

hierarchyProto._editNode = function (node) {
    var self = this;
    var prevTitle = node.title,
    tree = node.tree;
    // Disable dynatree mouse- and key handling
    tree.widget._unbind();
    // Replace node with <input>
    $(".fancytree-title", node.span).html("<input id='editNode' value='" + prevTitle + "'>");
    // Focus <input> and bind keyboard handler
    $("input#editNode")
      .focus()
      .keydown(function (event) {
          switch (event.which) {
              case 27: // [esc]
                  // discard changes on [esc]
                  $("input#editNode").val(prevTitle);
                  $(this).blur();
                  break;
              case 13: // [enter]
                  // simulate blur to accept new value
                  $(this).blur();
                  break;
          }
      }).blur(function (event) {
          // Accept new value, when user leaves <input>
          var title = $("input#editNode").val();
          if (title != prevTitle) {
              node.setTitle(title);
              self.NodeEdited.fire(self, {
                  node: node
              });
          }
          // Re-enable mouse and keyboard handlling
          tree.widget._bind();
          //node.focus();
      });
};

hierarchyProto = null;

RFBR.KnowledgeBase.Hierarchy.registerClass("RFBR.KnowledgeBase.Hierarchy", RFBR.Object);